<template>
  <div class="game">
    <div v-if="isShowActions" class="mask actions">
      <button
        v-if="status === 'INITIALIZED'"
        class="call-to-action"
        @click="onStart"
      >
        Start Game
      </button>
      <div v-if="status === 'COLLIDED'">
        <div>Game Over!</div>
        <button class="call-to-action" @click="onRestart">Play again</button>
      </div>
    </div>
    <ScoreBoard :score="score" />

    <div class="board">
      <div
        ref="containerRef"
        class="board-grid"
        :tabindex="-1"
        @keydown="handleKeypress"
      >
        <div
          v-for="(item, index) in boardArray"
          :key="index"
          class="grid-item"
          :class="item"
        />
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref } from 'vue'
import ScoreBoard from './ScoreBoard.vue'
import { Status, Direction } from '../constants'
import useSnakeGame from '../composables/useSnakeGame'

const allowedKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'] as const
const keyDirectionMap: Record<(typeof allowedKeys)[number], Direction> = {
  ArrowUp: Direction.UP,
  ArrowDown: Direction.DOWN,
  ArrowLeft: Direction.LEFT,
  ArrowRight: Direction.RIGHT
}

const containerRef = ref<HTMLDivElement>()
const props = defineProps({
  width: {
    type: Number,
    default: 11
  },
  height: {
    type: Number,
    default: 11
  },
  fps: {
    type: Number,
    default: 4
  },
  withWalls: {
    type: Boolean,
    default: true
  }
})

const { status, start, boardArray, restart, changeDirection, score } =
  useSnakeGame({
    ...props
  })

const handleKeypress = (e: KeyboardEvent) => {
  const key = e.key as keyof typeof keyDirectionMap
  if (allowedKeys.includes(key)) {
    e.preventDefault()
    changeDirection(keyDirectionMap[key])
  }
}

const isShowActions = computed(() =>
  [Status.INITIALIZED, Status.COLLIDED].includes(status.value)
)
const focusBoard = () => containerRef.value && containerRef.value.focus()
const onStart = () => {
  focusBoard()
  start()
}
const onRestart = () => {
  focusBoard()
  restart()
}
</script>

<style scoped>
* {
  box-sizing: border-box;
}
.game {
  position: relative;
  width: 400px;
  height: 500px;
  background-color: #008990;
  padding: 20px;
}

.mask {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  position: absolute;
  z-index: 2;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  text-align: center;
  background-color: hsla(0, 0%, 100%, 0.8);
}

.call-to-action {
  appearance: none;
  display: inline-block;
  overflow: hidden;
  vertical-align: middle;
  max-width: 100%;
  border: 2px solid hsl(352, 100%, 66%);
  border-radius: 4px;
  padding: 0.6em 1.2em;
  font-weight: 600;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: hsl(0, 0%, 100%);
  background-color: hsl(352, 100%, 66%);
  cursor: pointer;
  transition: all 0.2s ease-in-out;
  user-select: none;
  box-shadow:
    0 2px 2px 0 rgba(0, 0, 0, 0.14),
    0 3px 1px -2px rgba(0, 0, 0, 0.2),
    0 1px 5px 0 rgba(0, 0, 0, 0.12);

  &::after {
    content: '›';
    display: inline-block;
    position: relative;
    width: 14px;
    margin-left: 8px;
    transition: transform 0.2s ease-in-out;
  }

  &:hover,
  &:focus {
    border-color: hsl(352, 65%, 51%);
    text-decoration: none;
    color: hsl(0, 0, 100%);
    background-color: hsl(352, 65%, 51%);
  }
  &:hover::after,
  &:focus::after {
    transform: translateX(2px);
  }
}

.board {
  height: 400px;

  .board-grid {
    display: grid;
    grid-template-columns: repeat(v-bind(width), minmax(0, 1fr));
    grid-template-rows: repeat(v-bind(height), minmax(0, 1fr));
    line-height: v-bind(height);
    width: 100%;
    height: 100%;
    outline: 0;
    margin: 0 auto;
  }

  .grid-item {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    &:nth-child(even) {
      background-color: hsla(183, 28%, 84%, 100%);
    }
    &:nth-child(odd) {
      background-color: hsla(183, 28%, 84%, 50%);
    }
  }
}
.snake {
  position: relative;
  background-repeat: no-repeat;
  background-size: contain;

  &::before {
    content: '';
    width: 100%;
    height: 100%;
    background-color: #008990;
    background-image: radial-gradient(
        circle,
        hsl(160, 100%, 33%) 15%,
        transparent 10%
      ),
      radial-gradient(circle, hsl(160, 100%, 33%) 15%, transparent 10%);
    background-position:
      0 0,
      10px 10px;
    background-size: 10px 10px;
  }

  /* Head */
  &.head::after {
    content: '';
    position: absolute;
    z-index: 1;
    width: 100%;
    height: 100%;
    background-image: url('/snake/face.svg');
    background-repeat: no-repeat;
    background-size: contain;
  }
  &.head.from-right {
    justify-content: flex-end;
  }
  &.head.from-left {
    justify-content: flex-start;
  }
  &.head.from-left::after {
    transform: rotate(180deg);
  }
  &.head.from-left::before {
    width: 70%;
    height: 70%;
    border-top-right-radius: 50%;
    border-bottom-right-radius: 50%;
  }

  &.head.from-up {
    align-items: flex-start;
  }
  &.head.from-up::after {
    transform: rotate(270deg);
  }

  &.head.from-down {
    align-items: flex-end;
  }
  &.head.from-down::after {
    transform: rotate(90deg);
  }

  &.head.from-right::before {
    width: 70%;
    height: 70%;
    border-top-left-radius: 50%;
    border-bottom-left-radius: 50%;
  }

  &.head.from-up::before {
    width: 70%;
    height: 70%;
    border-bottom-right-radius: 50%;
    border-bottom-left-radius: 50%;
  }

  &.head.from-down::before {
    width: 70%;
    height: 70%;
    border-top-right-radius: 50%;
    border-top-left-radius: 50%;
  }

  /* Tail */
  &.tail.to-right::before {
    height: 70%;
    border-top-left-radius: 50%;
    border-bottom-left-radius: 50%;
  }

  &.tail.to-left::before {
    height: 70%;
    border-top-right-radius: 50%;
    border-bottom-right-radius: 50%;
  }

  &.tail.to-up::before {
    width: 70%;
    border-bottom-right-radius: 50%;
    border-bottom-left-radius: 50%;
  }

  &.tail.to-down::before {
    width: 70%;
    border-top-right-radius: 50%;
    border-top-left-radius: 50%;
  }

  &.from-left.to-right::before,
  &.from-right.to-left::before {
    height: 70%;
  }

  &.from-down.to-up::before,
  &.from-up.to-down::before {
    width: 70%;
  }

  &.from-left.to-down,
  &.from-down.to-left {
    justify-content: flex-start;
    align-items: flex-end;
  }
  &.from-left.to-down::before,
  &.from-down.to-left::before {
    width: 85%;
    height: 85%;
    border-top-right-radius: 100%;
  }
  &.from-left.to-down::after,
  &.from-down.to-left::after {
    content: '';
    position: absolute;
    width: 15%;
    height: 15%;
    border-top-right-radius: 100%;
    background-color: hsla(183, 28%, 84%, 100%);
  }

  &.from-left.to-up,
  &.from-up.to-left {
    justify-content: flex-start;
    align-items: flex-start;
  }
  &.from-left.to-up::before,
  &.from-up.to-left::before {
    width: 85%;
    height: 85%;
    border-bottom-right-radius: 100%;
  }
  &.from-left.to-up::after,
  &.from-up.to-left::after {
    content: '';
    position: absolute;
    width: 15%;
    height: 15%;
    border-bottom-right-radius: 100%;
    background-color: hsla(183, 28%, 84%, 100%);
  }

  &.from-right.to-up,
  &.from-up.to-right {
    justify-content: flex-end;
    align-items: flex-start;
  }
  &.from-right.to-up::before,
  &.from-up.to-right::before {
    width: 85%;
    height: 85%;
    border-bottom-left-radius: 100%;
  }
  &.from-right.to-up::after,
  &.from-up.to-right::after {
    content: '';
    position: absolute;
    width: 15%;
    height: 15%;
    border-bottom-left-radius: 100%;
    background-color: hsla(183, 28%, 84%, 100%);
  }

  &.from-right.to-down,
  &.from-down.to-right {
    justify-content: flex-end;
    align-items: flex-end;
  }
  &.from-right.to-down::before,
  &.from-down.to-right::before {
    width: 85%;
    height: 85%;
    border-top-left-radius: 100%;
  }
  &.from-right.to-down::after,
  &.from-down.to-right::after {
    content: '';
    position: absolute;
    width: 15%;
    height: 15%;
    border-top-left-radius: 100%;
    background-color: white;
  }
}
.candy::before {
  content: '';
  display: block;
  width: 75%;
  height: 75%;
  background-image: url('/snake/corona.svg');
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
</style>
